﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using BCCommon;
using BCCommon.Extensions;
using BCCommon.Enums;
using BCEntity.Common.Payment.Payment;
using BCData.Common.Wallet;
using BCData.Common.Payment.Payment;
using BCDto.Common.Payment.Payment;
using BCDto.Common.Payment.PaymentRecord;
using BCDto.Website.User;
using BCService.Common.Payment.Payment.AliPayCsr;
using BCService.Common.Wallet;
using BCCommon.PaymentEnums;
using BCService.Trading.SaleContract;
using BCService.TMS.AgentWallet;
using BCDto.Sim.Admin.Admin;
using BCService.TMS.Order.Order;

namespace BCService.Common.Payment.Payment
{
    public class PaymentService : IPaymentService
    {
        private readonly IPaymentChannelData paymentChannelData;
        private readonly IPaymentRecordData paymentRecordData;
        //private readonly ISaleContractService saleContractService;
        //private readonly IVehicleServiceNotificationRecordService vehicleServiceNotificationRecordService;
        private readonly IOrderProcessService orderProcessService;
        private readonly IWalletService walletService;
        private readonly IAgentWalletService agentWalletService; 
        public PaymentService(IPaymentChannelData paymentChannelData,
            IPaymentRecordData paymentRecordData,
            //ISaleContractService saleContractService,
            //IVehicleServiceNotificationRecordService vehicleServiceNotificationRecordService,
            IOrderProcessService orderProcessService,
            IWalletService walletService,
            IAgentWalletService agentWalletService)
        {
            this.paymentChannelData = paymentChannelData;
            this.paymentRecordData = paymentRecordData;
            //this.saleContractService = saleContractService;
            //this.vehicleServiceNotificationRecordService = vehicleServiceNotificationRecordService;
            this.orderProcessService = orderProcessService;
            this.walletService = walletService;
            this.agentWalletService = agentWalletService;
        }
        #region 获取支付渠道列表
        public IEnumerable<ChannelDto> GetChannels(SourceAppType appType, FlowType orderType, SourceOSType osType,UserDto userDto)
        {
            List<ChannelDto> list = new List<ChannelDto>();

            var wallet = this.walletService.GetWalletByUserId(userDto.UserId, true);

            // TODO: 这里面的业务应该通过数据库配置实现。
            foreach (var item in this.paymentChannelData.GetPaymentChannels().Where(p => p.Enabled == true).OrderBy(p => p.Order))
            {
                var channel = new ChannelDto
                {
                    ChannelId = item.PaymentChannelId,
                    Name = item.Name,
                    Description = item.Description,
                    Tips = item.Tips,
                    Logo = item.Logo
                };

                if (item.PaymentChannelId == PaymentChannelType.Balance.ToString())
                {
                    if (orderType == FlowType.Recharge)
                    {
                        continue;
                    }

                    channel.RequirePassword = true;
                    channel.HasPassword = !string.IsNullOrEmpty(wallet.PayPassword);
                }

                //if (item.PaymentChannelId == PaymentChannelType.Cash.ToString())
                //{
                //    continue;
                //}

                if (item.PaymentChannelId == PaymentChannelType.Alipay.ToString())
                {
                    channel.HasAuth = wallet.AlipayAuthInfo != null;
                }

                if (item.PaymentChannelId == PaymentChannelType.Weixin.ToString())
                {
                    channel.HasAuth = wallet.WxPayAuthInfo != null;
                }

                var channelService = this.GetChannelService(appType, item.PaymentChannelId.AsEnum<PaymentChannelType>(), osType);

                channel.Balance = channelService.GetBalance(userDto);
                channel.Limit = channelService.GetLimit(userDto);

                list.Add(channel);
            }

            return list;
        }
        #endregion

        #region 获取提现支付渠道列表
        public IEnumerable<ChannelDto> GetTransferChannels(SourceAppType appType, FlowType orderType, SourceOSType osType)
        {
            IEnumerable<PaymentChannelEntity> channels = this.paymentChannelData.GetPaymentChannels();

            return channels.Where(p => p.AppliedTo.Split(',').Contains(((int)orderType).ToString())).OrderBy(p => p.Order).Select(p => new ChannelDto
            {
                ChannelId = p.PaymentChannelId,
                Name = p.Name,
                Description = p.Description,
                Tips = p.Tips,
                Logo = p.Logo
            }).ToArray();
        }
        #endregion

        public IChannelFactoryService GetChannelService(SourceAppType appType, PaymentChannelType channelType, SourceOSType osType)
        {
            IChannelFactoryService channelService = null;
            IServiceProvider serviceProvider = GeneralContainer.ServiceProvider;
            if (serviceProvider == null)
            {
                throw new ArgumentException("登录已超时，请重新登录!");
            }
            switch (channelType)
            {
                case PaymentChannelType.Alipay:
                    //channelService = serviceProvider.GetService<IAlipayService>();
                    channelService = serviceProvider.GetService<IAliPayCsrService>();
                    break;
                case PaymentChannelType.Balance:
                    channelService = serviceProvider.GetService<IBalancePayService>();
                    break;
                //case PaymentChannelType.BankCard:
                //    channelService = GeneralContainer.RequestServices.GetService<IBankCardPayService>();
                //    break;
                case PaymentChannelType.Weixin:
                    channelService = serviceProvider.GetService<IWeixinService>();
                    break;
                //case PaymentChannelType.Cash:
                //    channelService = serviceProvider.GetService<ICashPayService>();
                //    break;
            }

            if (channelService != null)
            {
                channelService.ChannelType = channelType;
                channelService.AppType = appType;
                channelService.OSType = osType;
            }

            return channelService;
        }

        /// <summary>
        /// 支付成功后与原始业务同步。
        /// </summary>
        /// <param name="userDto">用户信息 (支付回调无法通过 IApplicationContextService 获取用户信息，需要传入。)</param>
        /// <param name="paymentRecordDto">支付记录。</param>
        public void Synchronize(UserDto userDto, PaymentRecordDto paymentRecordDto)
        {
            // 先设置同步验签的时间，放前面放后面??!!!
            this.paymentRecordData.SetAsSignTime(paymentRecordDto.PaymentRecordId);

            if (paymentRecordDto.OrderType == FlowType.TMSOrder || paymentRecordDto.OrderType == FlowType.CodAndOrder)
            {
                this.orderProcessService.CheckSignCompleteToProcessOrderInformation((SourcePayerType)paymentRecordDto.Payer, paymentRecordDto.ReferenceNumber, paymentRecordDto.PaymentRecordId, paymentRecordDto.PaymentChannelId, paymentRecordDto.Amount);
            }
            // TODO: 这里以后要补齐验签通过后的各个业务的操作
            //if (paymentRecordDto.OrderType == FlowType.Shopping)
            //{
            //    this.saleContractService.PaymentSaleAmount(paymentRecordDto);
            //}

            // 余额充值
            if (paymentRecordDto.OrderType == FlowType.Recharge)
            {
                // TODO: 当前这里的支付渠道是随便写的，还不确定这里是什么等待测试过程中修复。
                walletService.BalanceRecharge(userDto, paymentRecordDto.Amount, paymentRecordDto.ReferenceNumber, paymentRecordDto.PaymentChannelId);
            }
            
            //if (paymentRecordDto.OrderType == PaymentOrderType.FreightInfoFee)
            //{
            //    this.orderService.BindingVehicle(paymentRecordDto);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.Cod)
            //{
            //    //订单和代收货款只存在于收货人付款，并且有代收货款金额的。
            //    this.orderService.UpdateCodStatusAndTime(paymentRecordDto.ReferenceNumber, paymentRecordDto.PaymentRecordId);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.JoinLearningService)
            //{
            //    // TODO: 增加 缴费完成后回调更新司机是否待培训为 True
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndPendingTraining(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.VehicleGpsDeviceRelatedService)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndVehicleGpsDeviceRelated(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.VehicleService)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndVehicleService(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.TrainingFirstMarkUp)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndTrainingFirstMarkUp(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.Amount, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.TrainingSecondMarkUp)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndTrainingSecondMarkUp(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.Amount, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.VehicleDeposit)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndVehicleDepositMarkUp(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.Amount, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.ReportingFee)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndVehicleApplyStopMarkUp(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.Amount, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.RecoverFee)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndVehicleApplyStopRecoverMarkUp(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.Amount, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.FirstService)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndVehicleFirstService(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.LiquidatedDamages)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndLiquidatedDamages(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType== PaymentOrderType.TerminateContract)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndTerminateContractAmount(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.ExceptionFine)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndExceptionFine(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.SuccessTime);
            //}
        }


        public void AgentSynchronize(AdminDto admin, PaymentRecordDto paymentRecordDto)
        {
            // 先设置同步验签的时间，放前面放后面??!!!
            this.paymentRecordData.SetAsSignTime(paymentRecordDto.PaymentRecordId);

            // TODO: 这里以后要补齐验签通过后的各个业务的操作
            //if (paymentRecordDto.OrderType == FlowType.Shopping)
            //{
            //    this.saleContractService.PaymentSaleAmount(paymentRecordDto);
            //}

            // 代理商余额充值
            if (paymentRecordDto.OrderType == FlowType.AgentRecharge)
            {

                // TODO: 当前这里的支付渠道是随便写的，还不确定这里是什么等待测试过程中修复。
                agentWalletService.BalanceRecharge(admin, paymentRecordDto.Amount, paymentRecordDto.ReferenceNumber, paymentRecordDto.PaymentChannelId);
            }

            //if (paymentRecordDto.OrderType == PaymentOrderType.FreightInfoFee)
            //{
            //    this.orderService.BindingVehicle(paymentRecordDto);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.Cod)
            //{
            //    //订单和代收货款只存在于收货人付款，并且有代收货款金额的。
            //    this.orderService.UpdateCodStatusAndTime(paymentRecordDto.ReferenceNumber, paymentRecordDto.PaymentRecordId);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.JoinLearningService)
            //{
            //    // TODO: 增加 缴费完成后回调更新司机是否待培训为 True
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndPendingTraining(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.VehicleGpsDeviceRelatedService)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndVehicleGpsDeviceRelated(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.VehicleService)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndVehicleService(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.TrainingFirstMarkUp)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndTrainingFirstMarkUp(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.Amount, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.TrainingSecondMarkUp)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndTrainingSecondMarkUp(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.Amount, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.VehicleDeposit)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndVehicleDepositMarkUp(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.Amount, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.ReportingFee)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndVehicleApplyStopMarkUp(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.Amount, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.RecoverFee)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndVehicleApplyStopRecoverMarkUp(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.Amount, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.FirstService)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndVehicleFirstService(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.LiquidatedDamages)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndLiquidatedDamages(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType== PaymentOrderType.TerminateContract)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndTerminateContractAmount(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.SuccessTime);
            //}

            //if (paymentRecordDto.OrderType == PaymentOrderType.ExceptionFine)
            //{
            //    this.vehicleServiceNotificationRecordService.UpdateDriverPaidAndExceptionFine(paymentRecordDto, paymentRecordDto.ReferenceNumber, paymentRecordDto.SuccessTime);
            //}
        }

        public IEnumerable<ChannelDto> GetAgentChannels(SourceAppType appType, FlowType orderType, SourceOSType osType, long agentRecordId)
        {
            List<ChannelDto> list = new List<ChannelDto>();

            var agentWallet = this.agentWalletService.GetWalletByAgentId(agentRecordId, true);

            // TODO: 这里面的业务应该通过数据库配置实现。
            foreach (var item in this.paymentChannelData.GetPaymentChannels().Where(p => p.Enabled == true).OrderBy(p => p.Order))
            {
                var channel = new ChannelDto
                {
                    ChannelId = item.PaymentChannelId,
                    Name = item.Name,
                    Description = item.Description,
                    Tips = item.Tips,
                    Logo = item.Logo
                };

                if (item.PaymentChannelId == PaymentChannelType.Balance.ToString())
                {
                    if (orderType == FlowType.Recharge)
                    {
                        continue;
                    }

                    channel.RequirePassword = true;
                    channel.HasPassword = !string.IsNullOrEmpty(agentWallet.PayPassword);
                }

                //if (item.PaymentChannelId == PaymentChannelType.Cash.ToString())
                //{
                //    continue;
                //}

                if (item.PaymentChannelId == PaymentChannelType.Alipay.ToString())
                {
                    channel.HasAuth = agentWallet.AlipayAuthInfo != null;
                }

                if (item.PaymentChannelId == PaymentChannelType.Weixin.ToString())
                {
                    channel.HasAuth = agentWallet.WxPayAuthInfo != null;
                }

                var channelService = this.GetChannelService(appType, item.PaymentChannelId.AsEnum<PaymentChannelType>(), osType);

                channel.Balance = channelService.GetAgentBalance(agentRecordId);
                channel.Limit = channelService.GetAgentLimit(agentRecordId);

                list.Add(channel);
            }

            return list;
        }
    }
}
